package imse.team0.processors;

import imse.team0.orders.Order;
import imse.team0.orderws.data.OrderType;
import org.apache.camel.Exchange;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * @author Eugen, 4/27/12 9:17 PM
 */
public class InternalOrderBuilder {

    private static Logger LOG = LoggerFactory.getLogger(InternalOrderBuilder.class);

    private OrderIDBuilderStrategy orderBuilder = new IncrementalOrderGenerator();

    public void buildOrder(Exchange exchange) {
        OrderType requestOrder = (OrderType) exchange.getIn().getBody(List.class).get(0);
        String clientID = requestOrder.getClientID();
        String receiptDate = (String) exchange.getIn().getHeader("ReceiptTime");
        String orderid = getOrderId(clientID, receiptDate);
        Order internalOrder = new Order(orderid, clientID, receiptDate);
        for (OrderType.OrderItem item : requestOrder.getOrderItem()) {
            internalOrder.addItem(new Order.OrderItem(item.getId(), item.getQty().intValue()));
        }
        exchange.getOut().setBody(internalOrder);
        exchange.getOut().setHeader("TotalQuantity", exchange.getIn().getHeader("TotalQuantity"));
        exchange.getOut().setHeader("ReceiptTime", exchange.getIn().getHeader("ReceiptTime"));
        LOG.debug("-----------------> Internal order with id = "+orderid+" was created");
    }

    private String getOrderId(String clientID, String receiptDate) {
        // Base64 hash of clientID+receiptDate
        //return Base64.encode(clientID + receiptDate);
        return orderBuilder.getId();
    }

/*    public void readOrder(@Header("TotalQuantity") int totalQty, @Body Order incomingOrder){
        Logger log = LoggerFactory.getLogger(getClass().getName());
        log.info("Received order. ID="+incomingOrder.orderid+", total quantity="+totalQty);
    }*/
}

/*taken from http://www.wikihow.com/Encode-a-String-to-Base64-With-Java*/
class Base64 {

    private static final String base64code = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
            + "abcdefghijklmnopqrstuvwxyz" + "0123456789" + "+/";

    private static final int splitLinesAt = 76;

    public static byte[] zeroPad(int length, byte[] bytes) {
        byte[] padded = new byte[length]; // initialized to zero by JVM
        System.arraycopy(bytes, 0, padded, 0, bytes.length);
        return padded;
    }

    public static synchronized String encode(String string) {

        String encoded = "";
        byte[] stringArray;
        try {
            stringArray = string.getBytes("UTF-8");  // use appropriate encoding string!
        } catch (Exception ignored) {
            stringArray = string.getBytes();  // use locale default rather than croak
        }
        // determine how many padding bytes to add to the output
        int paddingCount = (3 - (stringArray.length % 3)) % 3;
        // add any necessary padding to the input
        stringArray = zeroPad(stringArray.length + paddingCount, stringArray);
        // process 3 bytes at a time, churning out 4 output bytes
        // worry about CRLF insertions later
        for (int i = 0; i < stringArray.length; i += 3) {
            int j = ((stringArray[i] & 0xff) << 16) +
                    ((stringArray[i + 1] & 0xff) << 8) +
                    (stringArray[i + 2] & 0xff);
            encoded = encoded + base64code.charAt((j >> 18) & 0x3f) +
                    base64code.charAt((j >> 12) & 0x3f) +
                    base64code.charAt((j >> 6) & 0x3f) +
                    base64code.charAt(j & 0x3f);
        }
        // replace encoded padding nulls with "="
        return splitLines(encoded.substring(0, encoded.length() -
                paddingCount) + "==".substring(0, paddingCount));

    }

    public static String splitLines(String string) {

        String lines = "";
        for (int i = 0; i < string.length(); i += splitLinesAt) {

            lines += string.substring(i, Math.min(string.length(), i + splitLinesAt));
            // removed newlines since I don't need them...
            //lines += "\r\n";

        }
        return lines;

    }
}

class IncrementalOrderGenerator implements OrderIDBuilderStrategy{
    private static Logger LOG = LoggerFactory.getLogger(IncrementalOrderGenerator.class);
    private long id = 0;

    IncrementalOrderGenerator() {
        LOG.warn("------------> New instance of IncrementalOrderGenerator was created .");
    }

    public synchronized String getId() {
        long next_id = ++id;
        LOG.warn("---------------> Next returned id = "+next_id);
        return (next_id)+"";
    }
}

interface OrderIDBuilderStrategy {
    public String getId();
}
